/***
 * Copyright (c) 2021-2031 murenchao
 * fig is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.software.fig.rpc

import com.google.gson.Gson
import com.google.gson.internal.LinkedTreeMap
import cool.taomu.software.fig.classloader.FigClassLoader
import cool.taomu.software.fig.classloader.FigClassLoaderManage
import cool.taomu.software.fig.rpc.annotation.Rpc
import cool.taomu.software.fig.rpc.entity.RpcResultEntity
import cool.taomu.software.fig.rpc.inter.Callback
import cool.taomu.software.fig.rpc.inter.IRpc
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

class RpcProxy {
    def static <T> T getInstance(String ip, Class<? extends IRpc> zlass) {
        return getInstance(ip, 32768, zlass);
    }

    def static <T> T getInstance(String ip, Integer port, Class<? extends IRpc> zlass) {
        return Proxy.newProxyInstance(FigClassLoader.getSystemClassLoader(), #[zlass], new InvocationHandler() {
            override invoke(Object proxy, Method method, Object[] args) throws Throwable {
                val results = new RpcResultEntity();
                var fig = new FigClassLoaderManage();
                var client = fig.getBean(RpcClient) as RpcClient;
                client.ip = ip;
                client.port = port;
                client.init(new Callback<T>() {
                    override call(RpcResultEntity<T> value) {
                        results.result = value.result;
                    }
                });
                var ann = zlass.getAnnotation(Rpc);
                if (ann === null) {
                    throw new Throwable("接口未定义Rpc注解");
                }
                client.send(ann.value, method.name, args);
                if (results.result instanceof LinkedTreeMap) {
                    return new Gson().fromJson(new Gson().toJson(results.result),method.returnType);
                }
                return results.result;
            }
        }) as T;
    }
}
